package com.winit.cloudlink.message.internal.mapping;

import com.winit.cloudlink.common.AppID;
import com.winit.cloudlink.message.Constants;
import com.winit.cloudlink.message.Message;
import com.winit.cloudlink.message.handler.AbstractMessageHandler;
import com.winit.cloudlink.message.handler.MessageHandler;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by stvli on 2016/6/4.
 */
public class DirectMappingStrategy extends AbstractMappingStrategy implements MappingStrategy {
	@Override
	public String[] getQueueNames(MessageHandler messageHandler) {
		List<String> queueList = new ArrayList<String>();

		AbstractMessageHandler abstractMessageHandler = (AbstractMessageHandler) messageHandler;
		// 构建默认队列
		StringBuilder queueBuilder = new StringBuilder();
		queueBuilder.append(abstractMessageHandler.getMessageType())
				.append(abstractMessageHandler.getMessageTypeSuffix())
				.append(Constants.MESSAGE_ROUTING_KEY_SEPARATOR)
				.append(metadata.getApplicationOptions().getAppId2String());
		queueList.add(queueBuilder.toString());


		// 如果存在的话，构建任务分发子队列
		String[] shardKeys = abstractMessageHandler.getShardKeys();
		if (null != shardKeys && shardKeys.length > 0) {
			for (String shardKey : shardKeys) {
				if (StringUtils.isNotBlank(shardKey)) {
					queueBuilder = new StringBuilder();
					queueBuilder.append(abstractMessageHandler.getMessageType())
							.append(abstractMessageHandler.getMessageTypeSuffix())
							.append(Constants.MESSAGE_SHARD_KEY_SEPARATOR)
							.append(shardKey)
							.append(Constants.MESSAGE_ROUTING_KEY_SEPARATOR)
							.append(metadata.getApplicationOptions().getAppId2String());
					queueList.add(queueBuilder.toString());
				}
			}
		}

		String[] queues = queueList.toArray(new String[queueList.size()]);
		return queues;
	}

	@Override
	public void initalQueue(MessageHandler messageHandler) {
		declareQueues(messageHandler);
	}

	@Override
	public String getSendExchangeName(Message message) {
		return Constants.MESSAGE_DEFAULT_SEND_EXCHANGE_NAME;
	}

	@Override
	public String getSendRoutingKey(Message message) {
		return message.getHeaders().getRoutingKey();
//        MessageHeaders headers = (MessageHeaders) message.getHeaders();
//        StringBuffer sb = new StringBuffer();
//        sb.append(headers.getMessageType());
//        sb.append(Constants.MESSAGE_ROUTING_KEY_SEPARATOR);
//        sb.append(headers.getToApp());
//        return sb.toString();
	}

	/**
	 * 声明queue
	 */
	private void declareQueues(MessageHandler messageHandler) {
		String[] queueNames = getQueueNames(messageHandler);
		String routingKey = getRoutingKeyForReceiveBingToSend();
		String exchangeSendName = getSendExchangeName(null);
		String exchangeReceiveName = getReceiveExchangeName(messageHandler);

		if (null != queueNames && queueNames.length > 0) {
			for (String queueName : queueNames) {
				declareQueue(queueName, routingKey, exchangeSendName, exchangeReceiveName);
			}
		}
	}

	public void declareQueue(String queueName, String routingKey, String sendExchangeName, String receiveExchangeName) {
		Queue queue = new Queue(queueName, true, false, false);
		rabbitAdmin.declareQueue(queue); // 声明queue

		TopicExchange sendExchange = new TopicExchange(sendExchangeName, true, false);
		rabbitAdmin.declareExchange(sendExchange);

		DirectExchange receiveExchange = new DirectExchange(receiveExchangeName, true, false);
		rabbitAdmin.declareExchange(receiveExchange);

		Binding localBinding = BindingBuilder.bind(receiveExchange).to(sendExchange).with(routingKey);
		rabbitAdmin.declareBinding(localBinding);

		Binding queuebinding = BindingBuilder.bind(queue).to(receiveExchange).with(queueName);
		rabbitAdmin.declareBinding(queuebinding);
	}

	public String getRoutingKeyForReceiveBingToSend() {
		StringBuilder queueBuilder = new StringBuilder();
		AppID appId = metadata.getApplicationOptions().getAppId();
		queueBuilder.append(Constants.MESSAGE_DEFAULT_BINDINGKEY_SUFFIX).append(appId.getArea());
		return queueBuilder.toString();
	}

	public String getReceiveExchangeName(MessageHandler messageHandler) {
		return Constants.MESSAGE_DEFAULT_RECV_EXCHANGE_NAME;
	}
}
